package com.cencat.merchant.controller;

import com.cencat.common.result.Result;
import com.cencat.common.utils.PageUtils.PageResult;
import com.cencat.merchant.dto.DispatchCreateDTO;
import com.cencat.merchant.dto.DispatchQueryDTO;
import com.cencat.merchant.entity.DispatchRecordEntity;
import com.cencat.merchant.entity.DriverEntity;
import com.cencat.merchant.service.DispatchAlgorithmService;
import com.cencat.merchant.service.DispatchRecordService;
import com.cencat.merchant.vo.DispatchRecordVO;
import com.cencat.merchant.vo.DispatchStatisticsVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * 派单管理控制器
 * 
 * @author cencat
 * @since 2024
 */
@Slf4j
@RestController
@RequestMapping("/api/dispatch")
@RequiredArgsConstructor
@Tag(name = "派单管理", description = "智能派单相关接口")
public class DispatchController {
    
    private final DispatchAlgorithmService dispatchAlgorithmService;
    private final DispatchRecordService dispatchRecordService;
    
    /**
     * 创建派单
     */
    @PostMapping("/create")
    @Operation(summary = "创建派单", description = "根据订单信息创建派单")
    public Result<DispatchRecordVO> createDispatch(@Valid @RequestBody DispatchCreateDTO createDTO) {
        log.info("创建派单请求: {}", createDTO);
        
        try {
            DispatchRecordEntity record = dispatchRecordService.createDispatch(createDTO);
            DispatchRecordVO vo = dispatchRecordService.convertToVO(record);
            return Result.success(vo);
        } catch (Exception e) {
            log.error("创建派单失败", e);
            return Result.error("创建派单失败: " + e.getMessage());
        }
    }
    
    /**
     * 智能派单
     */
    @PostMapping("/intelligent/{orderId}")
    @Operation(summary = "智能派单", description = "使用智能算法进行派单")
    public Result<DispatchRecordVO> intelligentDispatch(
            @Parameter(description = "订单ID") @PathVariable Long orderId,
            @Parameter(description = "商家ID") @RequestParam Long merchantId,
            @Parameter(description = "订单位置信息") @RequestBody Map<String, Double> orderLocation) {
        
        log.info("智能派单请求 - 订单ID: {}, 商家ID: {}", orderId, merchantId);
        
        try {
            // 获取可用司机
            List<DriverEntity> availableDrivers = dispatchAlgorithmService.getAvailableDrivers(
                orderId, merchantId, orderLocation, 10.0); // 默认10公里范围
            
            if (availableDrivers.isEmpty()) {
                return Result.error("当前没有可用司机");
            }
            
            // 默认算法权重配置
            Map<String, Double> weights = Map.of(
                "distance", 0.4,
                "rating", 0.3,
                "load", 0.3
            );
            
            // 执行智能派单
            Long driverId = dispatchAlgorithmService.intelligentDispatch(
                orderId, merchantId, availableDrivers, orderLocation, weights);
            
            if (driverId == null) {
                return Result.error("派单失败，未找到合适的司机");
            }
            
            // 计算匹配度和距离
            DriverEntity selectedDriver = availableDrivers.stream()
                .filter(d -> d.getId().equals(driverId))
                .findFirst()
                .orElse(null);
            
            if (selectedDriver == null) {
                return Result.error("选中的司机信息异常");
            }
            
            Map<String, Double> driverLocation = Map.of(
                "latitude", selectedDriver.getCurrentLatitude().doubleValue(),
                "longitude", selectedDriver.getCurrentLongitude().doubleValue()
            );
            
            Double matchScore = dispatchAlgorithmService.calculateMatchScore(
                selectedDriver, orderId, orderLocation, weights);
            Double distance = dispatchAlgorithmService.calculateDistance(driverLocation, orderLocation);
            
            // 执行派单
            DispatchRecordEntity record = dispatchAlgorithmService.executeDispatch(
                orderId, driverId, 5, matchScore, distance); // 5-智能派单
            
            DispatchRecordVO vo = dispatchRecordService.convertToVO(record);
            return Result.success(vo);
            
        } catch (Exception e) {
            log.error("智能派单失败", e);
            return Result.error("智能派单失败: " + e.getMessage());
        }
    }
    
    /**
     * 手动派单
     */
    @PostMapping("/manual")
    @Operation(summary = "手动派单", description = "手动指定司机进行派单")
    public Result<DispatchRecordVO> manualDispatch(
            @Parameter(description = "订单ID") @RequestParam Long orderId,
            @Parameter(description = "司机ID") @RequestParam Long driverId,
            @Parameter(description = "派单备注") @RequestParam(required = false) String remark) {
        
        log.info("手动派单请求 - 订单ID: {}, 司机ID: {}", orderId, driverId);
        
        try {
            DispatchRecordEntity record = dispatchRecordService.manualDispatch(orderId, driverId, remark);
            DispatchRecordVO vo = dispatchRecordService.convertToVO(record);
            return Result.success(vo);
        } catch (Exception e) {
            log.error("手动派单失败", e);
            return Result.error("手动派单失败: " + e.getMessage());
        }
    }
    
    /**
     * 司机接单
     */
    @PostMapping("/accept/{recordId}")
    @Operation(summary = "司机接单", description = "司机接受派单")
    public Result<String> acceptDispatch(
            @Parameter(description = "派单记录ID") @PathVariable Long recordId,
            @Parameter(description = "司机ID") @RequestParam Long driverId) {
        
        log.info("司机接单请求 - 记录ID: {}, 司机ID: {}", recordId, driverId);
        
        try {
            boolean success = dispatchRecordService.acceptDispatch(recordId, driverId);
            return success ? Result.success("接单成功") : Result.error("接单失败");
        } catch (Exception e) {
            log.error("司机接单失败", e);
            return Result.error("接单失败: " + e.getMessage());
        }
    }
    
    /**
     * 司机拒单
     */
    @PostMapping("/reject/{recordId}")
    @Operation(summary = "司机拒单", description = "司机拒绝派单")
    public Result<String> rejectDispatch(
            @Parameter(description = "派单记录ID") @PathVariable Long recordId,
            @Parameter(description = "司机ID") @RequestParam Long driverId,
            @Parameter(description = "拒绝原因") @RequestParam String rejectReason) {
        
        log.info("司机拒单请求 - 记录ID: {}, 司机ID: {}, 拒绝原因: {}", recordId, driverId, rejectReason);
        
        try {
            boolean success = dispatchRecordService.rejectDispatch(recordId, driverId, rejectReason);
            return success ? Result.success("拒单成功") : Result.error("拒单失败");
        } catch (Exception e) {
            log.error("司机拒单失败", e);
            return Result.error("拒单失败: " + e.getMessage());
        }
    }
    
    /**
     * 取消派单
     */
    @PostMapping("/cancel/{recordId}")
    @Operation(summary = "取消派单", description = "取消派单")
    public Result<String> cancelDispatch(
            @Parameter(description = "派单记录ID") @PathVariable Long recordId,
            @Parameter(description = "取消原因") @RequestParam String cancelReason) {
        
        log.info("取消派单请求 - 记录ID: {}, 取消原因: {}", recordId, cancelReason);
        
        try {
            boolean success = dispatchAlgorithmService.cancelDispatch(recordId, cancelReason);
            return success ? Result.success("取消成功") : Result.error("取消失败");
        } catch (Exception e) {
            log.error("取消派单失败", e);
            return Result.error("取消失败: " + e.getMessage());
        }
    }
    
    /**
     * 重新派单
     */
    @PostMapping("/redispatch/{recordId}")
    @Operation(summary = "重新派单", description = "重新进行派单")
    public Result<DispatchRecordVO> redispatch(
            @Parameter(description = "原派单记录ID") @PathVariable Long recordId,
            @Parameter(description = "排除的司机ID列表") @RequestBody(required = false) List<Long> excludeDriverIds) {
        
        log.info("重新派单请求 - 原记录ID: {}, 排除司机: {}", recordId, excludeDriverIds);
        
        try {
            DispatchRecordEntity record = dispatchAlgorithmService.redispatch(recordId, excludeDriverIds);
            if (record == null) {
                return Result.error("重新派单失败");
            }
            DispatchRecordVO vo = dispatchRecordService.convertToVO(record);
            return Result.success(vo);
        } catch (Exception e) {
            log.error("重新派单失败", e);
            return Result.error("重新派单失败: " + e.getMessage());
        }
    }
    
    /**
     * 查询派单记录
     */
    @GetMapping("/records")
    @Operation(summary = "查询派单记录", description = "根据条件查询派单记录")
    public Result<PageResult<DispatchRecordVO>> getDispatchRecords(@Valid DispatchQueryDTO queryDTO) {
        log.info("查询派单记录请求: {}", queryDTO);
        
        try {
            PageResult<DispatchRecordVO> result = dispatchRecordService.queryDispatchRecords(queryDTO);
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询派单记录失败", e);
            return Result.error("查询失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取派单记录详情
     */
    @GetMapping("/records/{recordId}")
    @Operation(summary = "获取派单记录详情", description = "根据ID获取派单记录详情")
    public Result<DispatchRecordVO> getDispatchRecord(
            @Parameter(description = "派单记录ID") @PathVariable Long recordId) {
        
        log.info("获取派单记录详情请求 - 记录ID: {}", recordId);
        
        try {
            DispatchRecordVO vo = dispatchRecordService.getDispatchRecordById(recordId);
            return vo != null ? Result.success(vo) : Result.error("派单记录不存在");
        } catch (Exception e) {
            log.error("获取派单记录详情失败", e);
            return Result.error("获取详情失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取派单统计信息
     */
    @GetMapping("/statistics")
    @Operation(summary = "获取派单统计信息", description = "获取派单相关统计数据")
    public Result<DispatchStatisticsVO> getDispatchStatistics(
            @Parameter(description = "租户ID") @RequestParam Long tenantId,
            @Parameter(description = "开始日期") @RequestParam String startDate,
            @Parameter(description = "结束日期") @RequestParam String endDate) {
        
        log.info("获取派单统计信息请求 - 租户ID: {}, 时间范围: {} ~ {}", tenantId, startDate, endDate);
        
        try {
            DispatchStatisticsVO statistics = dispatchRecordService.getDispatchStatistics(tenantId, startDate, endDate);
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取派单统计信息失败", e);
            return Result.error("获取统计信息失败: " + e.getMessage());
        }
    }
}